#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>

#include "bmp.h"

int lcdfd; //lcd屏幕的文件描述符
int *lcdmem; //lcd屏幕的映射空间

//lcd初始化
int lcd_init()
{
    //用可读可写的方式打开LCD屏幕
    lcdfd = open("/dev/fb0",O_RDWR);
    if(lcdfd == -1)
    {
        perror("open /dev/fb0 failed");
        return -1;
    }

    //映射内存空间
    lcdmem = mmap(NULL, 
                800*480*4, 
                PROT_READ |PROT_WRITE,
                MAP_SHARED,
                lcdfd,
                0);
    if(lcdmem == MAP_FAILED)
    {
        perror("mmap failed");
        return -1;
    }
}

//lcd销毁
void lcd_destory()
{
    close(lcdfd);
    munmap(lcdmem,800*480*4);
}

//显示bmp图片: 
// bmpname  图片名称
// bmpx:图片宽度   
// bmpy:图片高度
// dx,dy 是图片显示时在屏幕坐标系中,左上角的坐标
int showbmp(char *bmpname,int bmpx,int bmpy,int dx,int dy)
{
    //打开bmp图片--图片名称,用 bmpname 参数传递进来
    int bmpfd = open(bmpname,O_RDWR);
    if( bmpfd == -1)
    {
        perror("open bmpname failed");
        return -1;
    }

    //先读取54字节头文件
    char headbuf[54];
    read( bmpfd , headbuf , 54);

    //再读取 RGB 颜色数据，图片大小为 bmpx*bmpy
    char bmpbuf[bmpx*bmpy*3];
    read( bmpfd , bmpbuf , bmpx*bmpy*3);

    //因为LCD屏幕是32位,所以需要组合BMP的RGB数据
    int lcdbuf[bmpx*bmpy];
    int i;
    for(i=0;i<bmpx*bmpy;i++)
        lcdbuf[i] =  bmpbuf[3*i+0] | bmpbuf[3*i+1]<<8 | bmpbuf[3*i+2]<<16;

    // C语言中三目运算符  c = a<b ? a:b
    // 这里是先判断 a<b ,如果为真(a确实小于b),那么结果为 c = a;
    // 如果为假( a是大于b的)，那么结果为 c = b;

    //判断屏幕和图片的尺寸大小，选择较小的那一个
    int x_limit = 800 < bmpx ? 800 : bmpx;
    int y_limit = 480 < bmpy ? 480 : bmpy;
    printf("x_limit=%d  y_limit=%d\n",x_limit,y_limit);

    //把图片显示到开发板上
    int x,y;
    for(x=0;x<x_limit && x+dx < 800;x++)
        for(y=0;y<y_limit && y+dy < 480 ;y++)
            *(lcdmem + (x+dx) + 800*(y+dy) ) = lcdbuf[x+bmpx*(bmpy-1-y)];

    //关闭文件
    close(bmpfd);
}

//特效--图片从左边开始向右边展开
int showbmp_left(char *bmpname,int bmpx,int bmpy,int dx,int dy)
{
    //打开bmp图片--图片名称,用 bmpname 参数传递进来
    int bmpfd = open(bmpname,O_RDWR);
    if( bmpfd == -1)
    {
        perror("open bmpname failed");
        return -1;
    }

    //先读取54字节头文件
    char headbuf[54];
    read( bmpfd , headbuf , 54);

    //再读取 RGB 颜色数据，图片大小为 bmpx*bmpy
    char bmpbuf[bmpx*bmpy*3];
    read( bmpfd , bmpbuf , bmpx*bmpy*3);

    //因为LCD屏幕是32位,所以需要组合BMP的RGB数据
    int lcdbuf[bmpx*bmpy];
    int i;
    for(i=0;i<bmpx*bmpy;i++)
        lcdbuf[i] =  bmpbuf[3*i+0] | bmpbuf[3*i+1]<<8 | bmpbuf[3*i+2]<<16;

    // C语言中三目运算符  c = a<b ? a:b
    // 这里是先判断 a<b ,如果为真(a确实小于b),那么结果为 c = a;
    // 如果为假( a是大于b的)，那么结果为 c = b;

    //判断屏幕和图片的尺寸大小，选择较小的那一个
    int x_limit = 800 < bmpx ? 800 : bmpx;
    int y_limit = 480 < bmpy ? 480 : bmpy;
    printf("x_limit=%d  y_limit=%d\n",x_limit,y_limit);

    //把图片显示到开发板上
    int x,y;
    for(x=0;x<x_limit && x+dx < 800;x++)
    {
        for(y=0;y<y_limit && y+dy < 480 ;y++)
            *(lcdmem + (x+dx) + 800*(y+dy) ) = lcdbuf[x+bmpx*(bmpy-1-y)];

        usleep(10000);//延时 100000us == 100ms
    }
      
    //关闭文件
    close(bmpfd);
}

//特效--图片从上面向下面展开
int showbmp_up(char *bmpname,int bmpx,int bmpy,int dx,int dy)
{
    //打开bmp图片--图片名称,用 bmpname 参数传递进来
    int bmpfd = open(bmpname,O_RDWR);
    if( bmpfd == -1)
    {
        perror("open bmpname failed");
        return -1;
    }

    //先读取54字节头文件
    char headbuf[54];
    read( bmpfd , headbuf , 54);

    //再读取 RGB 颜色数据，图片大小为 bmpx*bmpy
    char bmpbuf[bmpx*bmpy*3];
    read( bmpfd , bmpbuf , bmpx*bmpy*3);

    //因为LCD屏幕是32位,所以需要组合BMP的RGB数据
    int lcdbuf[bmpx*bmpy];
    int i;
    for(i=0;i<bmpx*bmpy;i++)
        lcdbuf[i] =  bmpbuf[3*i+0] | bmpbuf[3*i+1]<<8 | bmpbuf[3*i+2]<<16;

    // C语言中三目运算符  c = a<b ? a:b
    // 这里是先判断 a<b ,如果为真(a确实小于b),那么结果为 c = a;
    // 如果为假( a是大于b的)，那么结果为 c = b;

    //判断屏幕和图片的尺寸大小，选择较小的那一个
    int x_limit = 800 < bmpx ? 800 : bmpx;
    int y_limit = 480 < bmpy ? 480 : bmpy;
    printf("x_limit=%d  y_limit=%d\n",x_limit,y_limit);

    //把图片显示到开发板上
    int x,y;
    for(y=0;y<y_limit && y+dy < 480 ;y++)
    {
        for(x=0;x<x_limit && x+dx < 800;x++)
            *(lcdmem + (x+dx) + 800*(y+dy) ) = lcdbuf[x+bmpx*(bmpy-1-y)];

        usleep(10000);//延时 100000us == 100ms
    }
      
    //关闭文件
    close(bmpfd);
}

//清屏
void screen_clear()
{
    int x,y;
    for(x=0;x< 800;x++)
        for(y=0;y< 480 ;y++)
            *(lcdmem + x+ 800*y ) = 0x00FFFFFF;//白色

}

